package com.gooseeker.mbus;

import java.io.IOException;
import java.util.TooManyListenersException;
import java.util.concurrent.TimeUnit;

import gnu.io.CommPortIdentifier;
import gnu.io.NoSuchPortException;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;

import org.apache.log4j.Logger;

import com.gooseeker.business.MonitorService;
import com.gooseeker.modbus.bean.SensorResultBean;
import com.gooseeker.modbus.bean.StationInfoBean;
import com.gooseeker.util.Constants;

public class Modbus {
	private Logger logger = Logger.getLogger(Modbus.class);
	private SerialPort serialPort = null;
	private boolean isConnected = false;
	private static Modbus theInstance = new Modbus();
	private MonitorService monitorService;
	
	public void setMonitorService(MonitorService monitorService) {
		this.monitorService = monitorService;
	}
	public static Modbus getInstance()
	{
		return theInstance;
	}
	/**
	 * 初始化
	 * 先清理，然后执行
	 * @param port
	 */
	public void init(String port)
	{
		//首先清理DATA_MAP缓存
		Modbus.getInstance().clean();
		//20秒后执行检查，发现创建时间超过10秒的数据则处理
		Constants.CHECK_THREAD_POOL.schedule(new CheckDataThread(), 20, TimeUnit.SECONDS);
		
		if(isConnected && serialPort != null)
		{
			return;
		}
		
		try 
		{
			CommPortIdentifier portId = CommPortIdentifier.getPortIdentifier(port);
			serialPort = (SerialPort) portId.open("SerialReader",Constants.DEFAULT_OPEN_TIMEOUT);
			serialPort.addEventListener(new SerialPortEventListenerImpl(serialPort.getInputStream()));
			serialPort.notifyOnDataAvailable(true);
			serialPort.setSerialPortParams(Constants.DEFAULT_COM_BUAD_RATE,Constants.DEFAULT_COM_DATA_BIT, Constants.DEFAULT_COM_STOP_BIT,Constants.DEFAULT_COM_PARITY);
			isConnected = true;
			logger.info(port + "init success, buad=" + Constants.DEFAULT_COM_BUAD_RATE);
		} catch (NoSuchPortException e) {
			logger.error(port + "the port not exists ." + e.getMessage());
		} catch (PortInUseException e) {
			logger.error(port + "the port in use ." + e.getMessage());
		} catch (TooManyListenersException e) {
			logger.error(port + "the port listeners toomany ." + e.getMessage());
		} catch (UnsupportedCommOperationException e) {
			logger.error(port + "the port unsupport comm operate ." + e.getMessage());
		} catch (IOException e) {
			logger.error(port + "the port inputstream error ." + e.getMessage());
		}
	}
	
	public void sendCommend(byte[] cmd)
	{
		if (cmd == null || cmd.length <= 0)
		{
			logger.error("error . cmd is null ");
			return;
		}
		
		try 
		{
			if(serialPort != null)
			{
				serialPort.getOutputStream().write(cmd);
			}
			else
			{
				logger.error("send cmd error . serial port is null .");
			}
		} catch (IOException e) {
			logger.error("send cmd error . "+e.getMessage());
			//关闭串口
			close();
		}
	}
	
	public void close()
	{
		if(isConnected)
		{
			serialPort.notifyOnDataAvailable(false);
			serialPort.removeEventListener();
			serialPort.close();
			isConnected = false;
		}
	}
	
	public void clean()
	{
		Constants.DATA_MAP.clear();
	}
	
	/**
	 * 记录数据库
	 * @param info
	 * @param result
	 */
	public void insertToDB(StationInfoBean info, SensorResultBean result)
	{
		try
		{
			long ret = monitorService.insertMonitorWithAddress(
					info.getAddress(), info.getSubAddress(),
					result.getState(), result.getValue1() + "|" + result.getValue2());
			

			if (ret <= 0)
			{
				logger.error("insert to db fail ." + "[addr=" + info.getAddress()
						+ ", subaddr=" + info.getSubAddress() + ", value="
						+ result.getValue1() + "|" + result.getValue2() + " state = " + result.getState());
			}
			else
			{
				logger.info("insert to db success：" + ret + "[addr=" + info.getAddress()
						+ ", subaddr=" + info.getSubAddress() + ", value="
						+ result.getValue1() + "|" + result.getValue2() + " state = " + result.getState());
			}
		}
		catch (Exception e)
		{
			logger.error("insert data to db error: " + e.getMessage());
		}
	}
	
}
